package com.example.domain.valueobject;

import lombok.Data;
import java.math.BigDecimal;
import java.util.Objects;

/**
 * 折扣计算结果值对象
 * 封装折扣计算的完整结果信息，适用于所有类型的折扣计算
 * 
 * <p>适用场景：
 * <ul>
 *   <li>单品折扣：针对单个商品的折扣计算</li>
 *   <li>满减折扣：针对购物车总额的满减计算</li>
 *   <li>其他折扣：N元购、买N送N等（预留扩展）</li>
 * </ul>
 * </p>
 *
 * @author Means
 * @since 2025-11-11
 */
@Data
public class DiscountResult {
    
    /** 原价金额 */
    private final BigDecimal originalAmount;
    
    /** 折后金额 */
    private final BigDecimal discountedAmount;
    
    /** 折扣金额（优惠了多少） */
    private final BigDecimal discountAmount;
    
    /** 折扣描述（如"8折"、"满100减10"） */
    private final String description;
    
    /** 规则ID */
    private final String ruleId;
    
    /** 规则名称 */
    private final String ruleName;
    
    /** 折扣类型（PERCENTAGE-百分比折扣, THRESHOLD-满减, FIXED_PRICE-特价, NONE-无折扣） */
    private final String discountType;
    
    /**
     * 私有构造函数
     * 
     * @param originalAmount 原价金额
     * @param discountedAmount 折后金额
     * @param discountAmount 折扣金额
     * @param description 折扣描述
     * @param ruleId 规则ID
     * @param ruleName 规则名称
     * @param discountType 折扣类型
     */
    private DiscountResult(BigDecimal originalAmount, BigDecimal discountedAmount,
                          BigDecimal discountAmount, String description,
                          String ruleId, String ruleName, String discountType) {
        this.originalAmount = originalAmount;
        this.discountedAmount = discountedAmount != null ? discountedAmount : originalAmount;
        this.discountAmount = discountAmount != null ? discountAmount : BigDecimal.ZERO;
        this.description = description != null ? description : "";
        this.ruleId = ruleId;
        this.ruleName = ruleName;
        this.discountType = discountType != null ? discountType : "NONE";
    }
    
    /**
     * 创建无折扣结果
     * 
     * @param originalAmount 原价金额
     * @return 折扣结果对象
     */
    public static DiscountResult noDiscount(BigDecimal originalAmount) {
        return new DiscountResult(originalAmount, originalAmount, BigDecimal.ZERO,
                                "", null, null, "NONE");
    }
    
    /**
     * 创建有折扣结果
     * 
     * @param originalAmount 原价金额
     * @param discountedAmount 折后金额
     * @param description 折扣描述
     * @param ruleId 规则ID
     * @param ruleName 规则名称
     * @param discountType 折扣类型
     * @return 折扣结果对象
     */
    public static DiscountResult withDiscount(BigDecimal originalAmount, BigDecimal discountedAmount,
                                            String description, String ruleId, String ruleName, String discountType) {
        BigDecimal discountAmount = originalAmount.subtract(discountedAmount);
        return new DiscountResult(originalAmount, discountedAmount, discountAmount,
                                description, ruleId, ruleName, discountType);
    }
    
    /**
     * 是否有折扣
     * 
     * @return 是否有折扣
     */
    public boolean hasDiscount() {
        return discountAmount.compareTo(BigDecimal.ZERO) > 0;
    }
    
    /**
     * 是否无折扣
     * 
     * @return 是否无折扣
     */
    public boolean isNoDiscount() {
        return !hasDiscount();
    }
    
    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        DiscountResult that = (DiscountResult) o;
        return originalAmount.compareTo(that.originalAmount) == 0 &&
               discountedAmount.compareTo(that.discountedAmount) == 0 &&
               discountAmount.compareTo(that.discountAmount) == 0 &&
               Objects.equals(description, that.description) &&
               Objects.equals(ruleId, that.ruleId) &&
               Objects.equals(discountType, that.discountType);
    }
    
    @Override
    public int hashCode() {
        return Objects.hash(originalAmount, discountedAmount, discountAmount, 
                          description, ruleId, discountType);
    }
    
    @Override
    public String toString() {
        if (isNoDiscount()) {
            return String.format("DiscountResult{amount=%s, noDiscount}", originalAmount);
        }
        return String.format("DiscountResult{original=%s, discounted=%s, discount=%s, desc='%s', type=%s}",
                           originalAmount, discountedAmount, discountAmount, description, discountType);
    }
}

